import base64
import bz2
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys

from addconnection import *
from connections_ui import *

class Connections(QDialog, Ui_connections):
    
    """Manage connection list"""
    
    def __init__(self, *args):
        QDialog.__init__(self, *args)
        self.setupUi(self)
        self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
        self.connections = []
        self.defaultConn = 0
        
        # Dialog for adding/modifying a connection
        self.addDialog = AddConnection(self)
        
        # Push buttons
        self.connect(self.addButton, SIGNAL("clicked()"), self.onAdd)
        self.connect(self.modifyButton, SIGNAL("clicked()"), self.onModify)
        self.connect(self.defaultButton, SIGNAL("clicked()"), self.onSetDefault)
        self.connect(self.deleteButton, SIGNAL("clicked()"), self.onDelete)
        self.connect(self.closeButton, SIGNAL("clicked()"), self.accept)
        if uiplatform.name == "maemo":
            self.closeButton.setVisible(False)

        # Handle listbox selection
        self.connect(self.listWidget, SIGNAL("itemSelectionChanged()"), 
                     self.onSelect)
        self.connect(self.listWidget, 
                     SIGNAL("itemDoubleClicked(QListWidgetItem *)"),
                     self.onDoubleClick)
        
        # Restore configuration
        self.loadConfig()
        
    def onAdd(self):
        """Add new connection"""
        self.addDialog.setWindowTitle("Add connection - vpntool")
        self.addDialog.resetFields()
        if self.addDialog.exec_():
            fields = self.addDialog.fields()
            sel = len(self.connections)
            self.connections.append(fields)
            self.listWidget.addItem(fields["name"])
            self.listWidget.setCurrentItem(self.listWidget.item(sel))
            if sel == 0:
                self.setDefault(0)
            self.saveConfig()
        
    def onModify(self):
        """Modify selected connection's parameters"""
        self.addDialog.setWindowTitle("Modify connection - vpntool")
        sel = self.listWidget.currentRow()
        self.addDialog.setFields(self.connections[sel])
        ret = self.addDialog.exec_()
        if ret:
            fields = self.addDialog.fields()
            self.connections[sel] = fields
            self.listWidget.item(sel).setText(fields["name"])
            self.setDefault(self.defaultConn)
            self.saveConfig()
    
    def onDelete(self):
        """Delete selected connection"""
        sel = self.listWidget.currentRow()
        ret = QMessageBox(QMessageBox.Question, "Delete connection - vpntool", 
                          "Are you sure to delete connection \"%s\"?" % \
                            self.connections[sel]["name"],
                          QMessageBox.Yes | QMessageBox.No, self).exec_()
        if ret == QMessageBox.Yes:
            del self.connections[sel]
            self.listWidget.takeItem(sel)
            if sel == self.defaultConn:
                self.setDefault(0)
            self.saveConfig()
    
    def onSetDefault(self):
        """Set selected connection as default"""
        self.setDefault(self.listWidget.currentRow())
        self.saveConfig()
        
    def setDefault(self, index):
        """Set given connection as default"""
        if len(self.connections):
            if self.defaultConn >= 0:
                self.listWidget.item(self.defaultConn).\
                    setText(self.connections[self.defaultConn]["name"])
            self.listWidget.item(index).\
                setText(self.connections[index]["name"] + " (default)")
        self.defaultConn = index        
        
    def saveConfig(self):
        """Save connections"""
        settings = QSettings("vpntool", "Global")
        settings.setValue("size", QtCore.QVariant(self.size()))
        count = len(self.connections)
        settings.setValue("connections", QtCore.QVariant(count))
        settings.setValue("default", QtCore.QVariant(self.defaultConn))
        for i in xrange(0, count):
            settings = QtCore.QSettings("vpntool", "Connection%u" % i)
            settings.setValue("name", QVariant(self.connections[i]["name"]))
            settings.setValue("gateway", 
                QVariant(self.connections[i]["gateway"]))
            settings.setValue("group", QVariant(self.connections[i]["group"]))
            settings.setValue("groupPassword", 
                QVariant(scramble(self.connections[i]["groupPassword"])))
            settings.setValue("user", QVariant(self.connections[i]["user"]))
            settings.setValue("userPassword",
                QVariant(scramble(self.connections[i]["userPassword"])))
            settings.setValue("domain", QVariant(self.connections[i]["domain"]))
            settings.setValue("nattMode", 
                QVariant(self.connections[i]["nattMode"]))
            settings.setValue("vendor", 
                QVariant(self.connections[i]["vendor"]))
            settings.setValue("dh", QVariant(self.connections[i]["dh"]))
            settings.setValue("pfs", QVariant(self.connections[i]["pfs"]))
            settings.setValue("esd", QVariant(self.connections[i]["esd"]))
            settings.setValue("ene", QVariant(self.connections[i]["ene"]))
            settings.setValue("ifMode",
                QVariant(self.connections[i]["ifMode"]))
            settings.setValue("localAddress",
                QVariant(self.connections[i]["localAddress"]))
            settings.setValue("localPort",
                QVariant(self.connections[i]["localPort"]))
            settings.setValue("localUdpPort",
                QVariant(self.connections[i]["localUdpPort"]))
            settings.setValue("dpdIdle",
                QVariant(self.connections[i]["dpdIdle"]))
            settings.setValue("authMode",
                QVariant(self.connections[i]["authMode"]))
            settings.setValue("caFile",
                QVariant(self.connections[i]["caFile"]))
            settings.setValue("caDir",
                QVariant(self.connections[i]["caDir"]))
            settings.setValue("targetNetwork",
                QVariant(self.connections[i]["targetNetwork"]))
            settings.setValue("script",
                QVariant(self.connections[i]["script"]))
    
    def loadConfig(self):
        """Load connections"""
        self.connections  = []
        self.listWidget.clear()
        settings = QSettings("vpntool", "Global")
        self.defaultConn = settings.value("default").toInt()[0]
        count = settings.value("connections").toInt()[0]
        for i in xrange(0, count):
            settings = QSettings("vpntool", "Connection%u" % i)
            name = str(settings.value("name").toString())
            gateway = str(settings.value("gateway").toString())
            group = str(settings.value("group").toString())
            groupPassword = \
                descramble(settings.value("groupPassword").toString())
            user = str(settings.value("user").toString())
            userPassword = \
                descramble(settings.value("userPassword").toString())
            domain = str(settings.value("domain").toString())
            nattMode = settings.value("nattMode").toInt()[0]
            vendor = settings.value("vendor").toInt()[0]
            dh = settings.value("dh", QVariant(1)).toInt()[0]
            pfs = settings.value("pfs", QVariant(4)).toInt()[0]
            esd = settings.value("esd").toInt()[0]
            ene = settings.value("ene").toInt()[0]
            ifMode = settings.value("ifMode").toInt()[0]
            localAddress = str(settings.value("localAddress", 
                QVariant("0.0.0.0")).toString())
            localPort = settings.value("localPort", QVariant(500)).toInt()[0]
            localUdpPort = settings.value("localUdpPort", 
                QVariant(10000)).toInt()[0]
            dpdIdle = settings.value("dpdIdle", QVariant(300)).toInt()[0]
            authMode = settings.value("authMode").toInt()[0]
            caFile = str(settings.value("caFile").toString())
            caDir = str(settings.value("caDir").toString())
            targetNetwork = str(settings.value("targetNetwork", 
                QVariant("0.0.0.0/0.0.0.0")).toString())
            script = str(settings.value("script").toString())
            self.connections.append({"name": name,
                                     "gateway": gateway,
                                     "group": group,
                                     "groupPassword": groupPassword,
                                     "user": user,
                                     "userPassword": userPassword,
                                     "domain": domain,
                                     "nattMode": nattMode,
                                     "vendor": vendor,
                                     "dh": dh,
                                     "pfs": pfs,
                                     "esd": esd,
                                     "ene": ene,
                                     "ifMode": ifMode,
                                     "localAddress": localAddress,
                                     "localPort": localPort,
                                     "localUdpPort": localUdpPort,
                                     "dpdIdle": dpdIdle,
                                     "authMode": authMode,
                                     "caFile": caFile,
                                     "caDir": caDir,
                                     "targetNetwork": targetNetwork,
                                     "script": script,
                                    })
            if i == self.defaultConn:
                self.listWidget.addItem(name + " (default)")
            else:
                self.listWidget.addItem(name)
            
    def onSelect(self):
        """Handle selection change in list widget"""
        enable = len(self.listWidget.selectedItems()) > 0
        self.modifyButton.setEnabled(enable)
        self.defaultButton.setEnabled(enable)
        self.deleteButton.setEnabled(enable)
        
    def onDoubleClick(self, item):
        """Handle double click on list widget"""
        self.onModify()
            

def scramble(s):
    return base64.encodestring(bz2.compress(str(s))[2:])


def descramble(s):
    try:
        return bz2.decompress("BZ" + base64.decodestring(str(s)))
    except:
        return ""
